<?php

namespace app\admin\model\workteam;

use think\Db;
use think\Exception;
use think\Hook;
use think\Model;
use traits\model\SoftDelete;

class Task extends Model
{

    // 表名
    protected $name = 'workteam_task';
    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';
    // 定义时间戳字段名
    protected $createTime = 'create_time';
    protected $updateTime = 'update_time';
    protected $deleteTime = false;
    // 追加属性
    protected $append = [
        'status_text',
    ];

    protected static function init()
    {
        self::event('after_insert', function ($row) {
            $title = \app\admin\model\workteam\Log::getTitle();
            \app\admin\model\workteam\Log::record($row->project_id, $row->id, $title ? $title : __("添加任务"),__("任务名称").":".$row['name']);
        });
        self::event('before_update', function ($row) {
            $changedData = $row->getChangedData();
            if ($changedData) {
                $title = \app\admin\model\workteam\Log::getTitle();
                \app\admin\model\workteam\Log::record($row->project_id, $row->id, $title ? $title : __("修改任务"), $changedData);
            }
        });
		self::event('after_update', function ($row) {
            $changedData = $row->getChangedData();
			if(!isset($changedData['cycle_id'])) {
				$row->project_name = Project::get($row->project_id)->name;
				Hook::listen('workteam_task_edit', $row);
			}
		});

    }

    public function getStatusList()
    {
        return ['-1' => __('关闭'), '1' => __('进行中'), '0' => __('未开始'), '2' => __('完成')];
    }

    public function getLevelList()
    {
        return ['1' => __('无优先级'), '2' => __('不重要'), '3' => __('次要'), '4' => __('主要'), '5' => __('紧急')];
    }

    protected function setCreateTimeAttr($value)
    {
        return $value && !is_numeric($value) ? strtotime($value) : ($value ? $value : null);
    }

    public function getStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
        $list = $this->getStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    /**
     * 负责人
     */
    public function admin()
    {
        return $this->belongsTo("\\app\\admin\\model\\Admin", 'admin_id', 'id', []);
    }

    /**
     * 创建人
     */
    public function cadmin()
    {
        return $this->belongsTo("\\app\\admin\\model\\Admin", 'create_admin_id');
    }

    /**
     * 关联项目
     */
    public function project()
    {
        return $this->belongsTo("\app\admin\model\workteam\Project", 'project_id');
    }

    /**
     * 归属部门
     */
    public function group()
    {
		$department = get_addon_info('department');
        if ($department && $department['state'] == 1) {
			return $this->belongsTo("\\app\\admin\\model\\department\\Department", 'group_id');
        }else{
			return $this->belongsTo("\\app\\admin\\model\\AuthGroup", 'group_id');
		}
        
    }

    /**
     * 父任务
     */
    public function ptask()
    {
        return $this->belongsTo("\\app\\admin\\model\\workteam\\Task", 'pid');
    }

    /**
     * 附件
     * @return \think\model\relation\HasMany
     */
    public function files()
    {
        return $this->hasMany('\app\admin\model\workteam\Files', 'task_id');
    }

    /**
     * 添加主任务
     * @param $project_id 项目ID或者项目对象
     * @param $params
     * @param array $extend
     */
    public function add($project_id, $params, $extend = array(), $cycle_type = 0, $cycle_id = 0)
    {
        if (is_numeric($project_id)) {
            $project_row = \app\admin\model\workteam\Project::get($project_id);
        } else {
            $project_row = $project_id;
        }
        if (!$project_row) {
            $this->error = __("项目不存在");
            return false;
        }

        //如果项目不是未开始和进行中的，都不给添加任务
        if (!in_array($project_row->status, [1, 0])) {
            $this->error = __("项目状态不正常");
            return false;
        }

        if ($extend) $params = array_merge($params, $extend);
        Db::startTrans();
        try {
            $name = str_replace("\\model\\", "\\validate\\", get_class($this));
            $validate = $name . '.add';
            $this->validateFailException(true)->validate($validate);

            //可得工时 刚开始是和计划工时是一样的
            $params['get_hours'] = $params['plan_hours'];

			if($cycle_type != 0 && $cycle_id != 0) $params['cycle_id'] = $cycle_id;
            $result = $this->allowField(true)->save($params);
			if($cycle_type != 0 && $cycle_id == 0){
				$this->cycle_id = $this->id;
				$this->save();
			}
            if ($result !== false) {
                $task_id = $this->id;
                //如果存在附件
                if (isset($params['image']) && $params['image']) {
                    $images = explode(",", $params['image']);
                    //获取附件名称集合
                    $attachments = \app\common\model\Attachment::where('url', 'in', $images)->column('filename', 'url');

                    $files_data = array();
                    foreach ($images as $key => $v) {
                        $files_data[$key]['url'] = $v;
                        $files_data[$key]['admin_id'] = $params['create_admin_id'];
                        $files_data[$key]['project_id'] = $project_id;
                        $files_data[$key]['task_id'] = $task_id;
                        $files_data[$key]['create_time'] = time();
                        $files_data[$key]['filename'] = isset($attachments[$v]) ? $attachments[$v] : $v;
                    }

                    $this->files()->saveAll($files_data);
                }


                $project_row->task_count++;
//                $project_row->task_hours = $project_row->task_hours + $params['plan_hours'];
				$project_row->task_hours = $this->getProjectTaskHours($project_row->id, 0);
                //如果任务是开始和完成就需要把未开始的项目开始
                if (in_array($params['status'], [1, 2])) {
                    if ($project_row->status == 0)
                        $project_row->status = 1;
                    if ($params['status'] == 2) {
                        $project_row->task_complate++;//完成任务数量
//                        $project_row->actual_hours = $project_row->actual_hours + $params['get_hours'];//完成工时
						$project_row->actual_hours = $this->getProjectActualHours($project_row->id, 0);
                    }
                }
                //项目参与人处理
                //admin_ids
                if (!in_array($params['admin_id'], explode(',', $project_row->admin_ids))) {
                    $project_row->admin_ids = $project_row->admin_ids ? $project_row->admin_ids . ',' . $params['admin_id'] : $params['admin_id'];
                }
                $project_row->save();

                $alert_data = $this->getAlertData($result);
                hook('workteam_task_add', $alert_data);
                Db::commit();

            } else {
                \exception($this->getError());
            }
        } catch (Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }
        return true;


    }

    /**
     * 添加子任务
     * @param $parent_task 主任务对象
     * @param $params 参数
     * @param array $extend
     */
    public function addchild($parent_task, $params, $extend = array(), $cycle_type = 0, $cycle_id = 0)
    {
        if (!$parent_task) {
            $this->error = __("主任务不存在");
            return false;
        }


        $params['start_time'] =!is_numeric($params['start_time']) ? strtotime($params['start_time']) :$params['start_time'];
        $params['end_time'] = !is_numeric($params['end_time']) ? strtotime($params['end_time']) : $params['end_time'];
        if ($extend) $params = array_merge($params, $extend);

        try {
            //是否采用模型验证
            $name = str_replace("\\model\\", "\\validate\\", get_class($this));
            $this->validate($name . '.add');

            if ($params['plan_hours'] > $parent_task['get_hours']) {
                //如果计划时间大于父类的获得工时就报错
                exception(__("剩余工时不足"));
            }
            //可得工时
            $params['get_hours'] = $params['plan_hours'];

			if($cycle_type != 0 && $cycle_id != 0) $params['cycle_id'] = $cycle_id;
            $result = $this->allowField(true)->save($params);
			if($cycle_type != 0 && $cycle_id == 0){
				$this->cycle_id = $this->id;
				$this->save();
			}

            if ($result !== false) {

                $task_id = $this->id;
                //如果存在附件
                if (isset($params['image']) && $params['image']) {
                    $images = explode(",", $params['image']);
                    //获取附件名称集合
                    $attachments = \app\common\model\Attachment::where('url', 'in', $images)->column('filename', 'url');

                    $files_data = array();
                    foreach ($images as $key => $v) {
                        $files_data[$key]['url'] = $v;
                        $files_data[$key]['admin_id'] = $params['create_admin_id'];
                        $files_data[$key]['project_id'] = $parent_task->project->id;
                        $files_data[$key]['task_id'] = $task_id;
                        $files_data[$key]['create_time'] = time();
                        $files_data[$key]['filename'] = isset($attachments[$v]) ? $attachments[$v] : $v;
                    }

                    $this->files()->saveAll($files_data);
                }


                $parent_task->project->task_count++;//项目任务数量
                //如果任务是开始和完成就需要把未开始的项目开始
                if (in_array($params['status'], [1, 2])) {
                    if ($parent_task->project->status == 0)
                        $parent_task->project->status = 1;
                    if ($params['status'] == 2) {
                        $parent_task->project->task_complate++;//完成任务数量
//                        $parent_task->project->actual_hours = $parent_task->project->actual_hours + $params['get_hours'];//完成工时
						$parent_task->project->actual_hours = $this->getProjectActualHours($parent_task->project->id, 0);
                    }
                }
                //项目参与人处理
                //admin_ids
                if (!in_array($params['admin_id'], explode(',', $parent_task->project->admin_ids))) {
                    $parent_task->project->admin_ids = $parent_task->project->admin_ids ? $parent_task->project->admin_ids . ',' . $params['admin_id'] : $params['admin_id'];
                }
                $parent_task->project->save();

//                $parent_task->get_hours = $parent_task->get_hours - $params['plan_hours'];//从父级减去工时
				$parent_task->get_hours = $this->getParentTaskGetHours($parent_task->id, $parent_task->plan_hours, 0);
                $parent_task->save();

				$alert_data = $this->getAlertData($result);
                hook('workteam_task_add', $alert_data);
                Db::commit();
            } else {
                \exception($this->getError());
            }
        } catch (Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }
        return  true;
    }

    /**
     * 我的工时
     * @param $startDate 开始时间
     * @param $endDate 结束时间
     * @return array|bool
     */
    public function getHoursEchart($startDate, $endDate, $owner_user_ids = null)
    {

        // 生成查询的开始和结束时间，默认取30日
        !is_numeric($startDate) && $starttime = strtotime($startDate);
        !is_numeric($endDate) && $endtime = strtotime($endDate);
        $isnotrangeDate = empty($starttime) && empty($endtime);
        $nearly = '30';
        if ($isnotrangeDate) {
            $endtime = time();
            $nearly -= 1;
            $starttime = strtotime("-{$nearly} day");  // 最近30天日期
        } elseif ($starttime > $endtime) {
            $this->error = '起始时间要小于终止时间';
            return false;
        }
        $totalseconds = $endtime - $starttime;;
        if ($totalseconds > 86400 * 30 * 2) {
            $format = '%Y-%m';
        } else {
            if ($totalseconds > 86400) {
                $format = '%Y-%m-%d';
            } else {
                $format = '%H:00';
            }
        }
        $tempwhere = array();
        if ($owner_user_ids && is_numeric($owner_user_ids)) {
            $tempwhere['admin_id'] = $owner_user_ids;
        } elseif ($owner_user_ids && is_array($owner_user_ids)) {
            $tempwhere['admin_id'] = ['in', $owner_user_ids];

        }
        //完成任务工时
        $lists = $this->where($tempwhere)->where('complete_time', 'between time', [$starttime, $endtime])
            ->field('COUNT(*) AS nums, sum(get_hours) as hours, DATE_FORMAT(FROM_UNIXTIME(complete_time), "' . $format . '") AS add_date')
            ->group('add_date')
            ->where('status', 2)
            ->select();
        //安排任务工时，开始时间为准
        $unlists = $this->where($tempwhere)->where('start_time', 'between time', [$starttime, $endtime])
            ->field('COUNT(*) AS nums, sum(get_hours) as hours, DATE_FORMAT(FROM_UNIXTIME(start_time), "' . $format . '") AS add_date')
            ->group('add_date')
            ->where('status', '<>', -1)
            ->select();


        if ($totalseconds > 84600 * 30 * 2) {
            $starttime = strtotime('last month', $starttime);
            while (($starttime = strtotime('next month', $starttime)) <= $endtime) {
                $column[] = date('Y-m', $starttime);
            }
        } else {
            if ($totalseconds > 86400) {
                for ($time = $starttime; $time <= $endtime;) {
                    $column[] = date("Y-m-d", $time);
                    $time += 86400;
                }
            } else {
                for ($time = $starttime; $time <= $endtime;) {
                    $column[] = date("H:00", $time);
                    $time += 3600;
                }
            }
        }


        $c_count = $c_hours = $s_hours = $s_count = array_fill_keys($column, 0);

        foreach ($lists as $k => $v) {
            $c_count[$v['add_date']] = $v['nums'];//任务完成数量
            $c_hours[$v['add_date']] = $v['hours'];//获得完成工时

        }
        foreach ($unlists as $k => $v) {
            $s_hours[$v['add_date']] = $v['hours'];//安排任务工时
            $s_count[$v['add_date']] = $v['nums']; //安排任务数量
        }

        $data = [
            'date' => array_keys($c_count),
            'data' => [
                __("获得工时") => array_values($c_hours),
                __("安排工时") => array_values($s_hours),

                __("完成数量") => array_values($c_count),
                __("安排数量") => array_values($s_count),

            ],
        ];
        return $data;
    }


    /**
     * 完成成任务
     * @param null $complete_time 完成时间
     * @param null $row
     * @return bool|false|int
     */
    public function complete(array $logData, $complete_time = null, $row = null)
    {
        $row = $row ? $row : $this;
        //如果项目不是未开始和进行中的，都不给标记完成
        if (!in_array($row->status, [1, 0])) {
//            $this->error = __('任务状态不正常。');
//            return false;
        }


        if (!$row->project) {
            $this->error = __('项目不存在');
            return false;
        }

        //如果项目不是未开始和进行中的，都不给完成
        if (!in_array($row->project->status, [1, 0])) {
//            $this->error = __('项目状态不允许完成');
//            return false;
        }
        if (!in_array($row->status, [1])) {
//            $this->error = __('任务状态不是进行中');
//            return false;
        }
        if ($row->project->status == 0) {
            $row->project->status = 1;//项目设置为进行中
        }

		$this->startTrans();
		try{
			// 完成任务
			$row->project->actual_hours = $row->project->actual_hours + $row->get_hours;//已经完成工时
			$row->project->task_complate++;//完成任务数量
			$row->project->save();
			$row->status = 2;
			$row->progress = 100;
			$row->complete_time = $complete_time ? $complete_time : time();
			$row->service_hours = $logData['service_hours'];
			$res = $row->save();
			\app\admin\model\workteam\Log::setTitle(__('完成任务'));

			// 客情记录
			if(!isset($logData['content']) || $logData['content'] == '') $logData['content'] = '完成任务：'.$row->project->name.' - '.$row['name'];
			if(!isset($logData['secret']) || $logData['secret'] == '') $logData['secret'] = $row->content;
			$logModel = new \app\admin\model\service\Log();
			$logModel->save($logData);

			$this->commit();
			return $res;
		}catch (Exception $exception){
			$this->error = $exception->getMessage();
			$this->rollback();
			return false;
		}

    }


    /**
     * 反完成任务
     * @param null $row
     * @return bool|false|int
     */
    public function ucomplete($row = null)
    {
        $row = $row ? $row : $this;
        //如果项目不是未开始和进行中的，都不给标记完成
        if ($row->status!=2) {
            $this->error = __('任务状态不是完成状态');
            return false;
        }


        if (!$row->project) {
            $this->error = __('项目不存在');
            return false;
        }

        //如果项目不是未开始和进行中的，都不给完成
        if (!in_array($row->project->status, [1, 0])) {
            $this->error = __('项目状态不允许修改');
            return false;
        }
        $row->project->actual_hours = $row->project->actual_hours - $row->get_hours;//已经完成工时
        $row->project->task_complate--;//完成任务数量
        $row->project->save();
        $row->status = 1;
        $row->complete_time =null;
        \app\admin\model\workteam\Log::setTitle(__('反完成任务'));
        return $row->save();

    }

	protected function getAlertData(){
		$data = $this->getData();
		$data['project_name'] = $this->project ? $this->project->name : '';
		$data['group_name'] = $this->group ? $this->group->name : '';

		$level_list = $this->getLevelList();
		$data['level_name'] = isset($level_list[$data['level']]) ? $level_list[$data['level']] : '';

		$adminModel = new \app\admin\model\Admin();
		$data['admin_name'] = $adminModel->where('id',$data['admin_id'])->value('nickname');
		$data['admin_names'] = $adminModel->where('id', 'in', $data['admin_ids'])->value('GROUP_CONCAT(nickname)');

		$data['link'] = config('admin.crm_url').url('workteam/task/edit',['ids'=>$this->id]);

		return $data;
	}

	/**
	 * 统计任务总工时
	 * @param $project_id
	 * @param $add_hours
	 * @param $task_id
	 * @return float|int|string
	 */
	public function getProjectTaskHours($project_id, $add_hours, $task_id = 0){
		$where = ['project_id' => $project_id, 'pid' => 0];
		if($task_id!=0) $where['id'] = ['<>', $task_id];
		$totalHours = $this->where($where)->sum('plan_hours') + $add_hours;
		return $totalHours;
	}

	/**
	 * 统计实际工时
	 * @param $project_id
	 * @param $add_hours
	 * @param $task_id
	 * @return float|int|string
	 */
	public function getProjectActualHours($project_id, $add_hours, $task_id = 0){
		$where = ['project_id' => $project_id, 'status' => 1];
		if($task_id!=0) $where['id'] = ['<>', $task_id];
		$totalHours = $this->where($where)->sum('get_hours') + $add_hours;
		return $totalHours;
	}

	/**
	 * 统计获得工时
	 * @param $parent_id
	 * @param $parent_plan_hours
	 * @param $add_hours
	 * @param $task_id
	 * @return float|int|string
	 */
	public function getParentTaskGetHours($parent_id, $parent_plan_hours, $add_hours, $task_id = 0){
		$where = ['pid' => $parent_id];
		if($task_id!=0) $where['id'] = ['<>', $task_id];
		$totalPlanHours = $this->where($where)->sum('plan_hours') + $add_hours;
		$getHours = $parent_plan_hours - $totalPlanHours;
		return $getHours;
	}

}
